package com.gitee.wsl.collections.observable.handler

interface AbstractObservableCollectionHandler<T> {
    fun onClear(elements: Collection<T>)
}

interface ObservableCollectionHandler<T> : AbstractObservableCollectionHandler<T> {
    fun onAdd(element: T)
    fun onRemove(element: T)
}

private typealias ClearBlock<T> = (elements: Collection<T>) -> Unit

abstract class AbstractObservableCollectionHandlerScope<T> {
    private var clearBlock: ClearBlock<T>? = null

    fun clear(block: ClearBlock<T>) {
        clearBlock = block
    }

    protected abstract inner class Handler : AbstractObservableCollectionHandler<T> {
        override fun onClear(elements: Collection<T>) {
            clearBlock?.invoke(elements)
        }
    }
}

private typealias CollectionElementBlock<T> = (element: T) -> Unit

class ObservableCollectionHandlerScope<T> : AbstractObservableCollectionHandlerScope<T>() {
    private var addBlock: CollectionElementBlock<T>? = null
    private var removeBlock: CollectionElementBlock<T>? = null

    fun add(block: CollectionElementBlock<T>) {
        addBlock = block
    }

    fun remove(block: CollectionElementBlock<T>) {
        removeBlock = block
    }

    private inner class Handler : AbstractObservableCollectionHandlerScope<T>.Handler(),
        ObservableCollectionHandler<T> {
        override fun onAdd(element: T) {
            addBlock?.invoke(element)
        }

        override fun onRemove(element: T) {
            removeBlock?.invoke(element)
        }
    }

    @PublishedApi
    internal fun createHandler(): ObservableCollectionHandler<T> = Handler()
}